package com.christina.engine.singleton;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 配置管理器单例
 * 负责管理系统的全局配置
 * 
 * @author Christina
 */
@Slf4j
@Component
public class ConfigurationManager {
    
    // 使用双重检查锁定的单例实现
    private static volatile ConfigurationManager instance;
    private static final Object lock = new Object();
    
    // 配置存储
    private final Map<String, Object> configurations = new ConcurrentHashMap<>();
    private final Map<String, ConfigurationMetadata> metadata = new ConcurrentHashMap<>();
    private final List<ConfigurationChangeListener> listeners = new CopyOnWriteArrayList<>();
    
    // 读写锁，用于配置的并发访问控制
    private final ReadWriteLock configLock = new ReentrantReadWriteLock();
    
    // 配置版本号，用于变更检测
    private volatile long configVersion = 0;
    
    // 私有构造函数，防止外部实例化
    private ConfigurationManager() {
        initializeDefaultConfigurations();
        log.info("ConfigurationManager initialized with version: {}", configVersion);
    }
    
    /**
     * 获取单例实例
     * 
     * @return 配置管理器实例
     */
    public static ConfigurationManager getInstance() {
        if (instance == null) {
            synchronized (lock) {
                if (instance == null) {
                    instance = new ConfigurationManager();
                }
            }
        }
        return instance;
    }
    
    /**
     * 初始化默认配置
     */
    private void initializeDefaultConfigurations() {
        // 系统配置
        setConfiguration("system.name", "Christina Assistant", "System name", false);
        setConfiguration("system.version", "1.0.0", "System version", true);
        setConfiguration("system.environment", "development", "Runtime environment", false);
        
        // 处理器配置
        setConfiguration("processor.chain.timeout", 30000L, "Processor chain timeout in milliseconds", false);
        setConfiguration("processor.validation.enabled", true, "Enable request validation", false);
        setConfiguration("processor.context.cache.enabled", true, "Enable context caching", false);
        
        // 策略配置
        setConfiguration("strategy.routing.default", "IntentBasedRouting", "Default routing strategy", false);
        setConfiguration("strategy.routing.fallback.enabled", true, "Enable routing fallback", false);
        
        // 执行器配置
        setConfiguration("executor.timeout", 60000L, "Service executor timeout in milliseconds", false);
        setConfiguration("executor.retry.enabled", true, "Enable executor retry", false);
        setConfiguration("executor.retry.maxAttempts", 3, "Maximum retry attempts", false);
        
        // 状态管理配置
        setConfiguration("state.timeout.default", 300000L, "Default state timeout in milliseconds", false);
        setConfiguration("state.persistence.enabled", false, "Enable state persistence", false);
        
        // 事件配置
        setConfiguration("event.async.enabled", true, "Enable async event processing", false);
        setConfiguration("event.queue.size", 1000, "Event queue size", false);
        setConfiguration("event.listener.timeout", 5000L, "Event listener timeout in milliseconds", false);
        
        // 缓存配置
        setConfiguration("cache.enabled", true, "Enable caching", false);
        setConfiguration("cache.ttl", 3600000L, "Cache TTL in milliseconds", false);
        setConfiguration("cache.maxSize", 10000, "Maximum cache size", false);
        
        // 日志配置
        setConfiguration("logging.level", "INFO", "Logging level", false);
        setConfiguration("logging.audit.enabled", true, "Enable audit logging", false);
        setConfiguration("logging.performance.enabled", true, "Enable performance logging", false);
        
        incrementVersion();
    }
    
    /**
     * 设置配置项
     * 
     * @param key 配置键
     * @param value 配置值
     * @param description 配置描述
     * @param readOnly 是否只读
     */
    public void setConfiguration(String key, Object value, String description, boolean readOnly) {
        if (key == null || key.trim().isEmpty()) {
            throw new IllegalArgumentException("Configuration key cannot be null or empty");
        }
        
        configLock.writeLock().lock();
        try {
            // 检查是否为只读配置
            ConfigurationMetadata existingMetadata = metadata.get(key);
            if (existingMetadata != null && existingMetadata.isReadOnly()) {
                throw new IllegalStateException("Configuration key '" + key + "' is read-only");
            }
            
            Object oldValue = configurations.get(key);
            configurations.put(key, value);
            
            // 更新元数据
            metadata.put(key, new ConfigurationMetadata(description, readOnly, System.currentTimeMillis()));
            
            incrementVersion();
            
            // 通知监听器
            notifyConfigurationChanged(key, oldValue, value);
            
            log.debug("Configuration updated: {} = {} (was: {})", key, value, oldValue);
            
        } finally {
            configLock.writeLock().unlock();
        }
    }
    
    /**
     * 设置配置项（默认非只读）
     * 
     * @param key 配置键
     * @param value 配置值
     */
    public void setConfiguration(String key, Object value) {
        setConfiguration(key, value, null, false);
    }
    
    /**
     * 获取配置项
     * 
     * @param key 配置键
     * @param defaultValue 默认值
     * @param <T> 配置值类型
     * @return 配置值
     */
    @SuppressWarnings("unchecked")
    public <T> T getConfiguration(String key, T defaultValue) {
        configLock.readLock().lock();
        try {
            Object value = configurations.get(key);
            return value != null ? (T) value : defaultValue;
        } finally {
            configLock.readLock().unlock();
        }
    }
    
    /**
     * 获取配置项
     * 
     * @param key 配置键
     * @return 配置值，如果不存在返回null
     */
    public Object getConfiguration(String key) {
        return getConfiguration(key, null);
    }
    
    /**
     * 获取字符串配置
     * 
     * @param key 配置键
     * @param defaultValue 默认值
     * @return 字符串配置值
     */
    public String getString(String key, String defaultValue) {
        return getConfiguration(key, defaultValue);
    }
    
    /**
     * 获取整数配置
     * 
     * @param key 配置键
     * @param defaultValue 默认值
     * @return 整数配置值
     */
    public Integer getInt(String key, Integer defaultValue) {
        Object value = getConfiguration(key);
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        return defaultValue;
    }
    
    /**
     * 获取长整数配置
     * 
     * @param key 配置键
     * @param defaultValue 默认值
     * @return 长整数配置值
     */
    public Long getLong(String key, Long defaultValue) {
        Object value = getConfiguration(key);
        if (value instanceof Number) {
            return ((Number) value).longValue();
        }
        return defaultValue;
    }
    
    /**
     * 获取布尔配置
     * 
     * @param key 配置键
     * @param defaultValue 默认值
     * @return 布尔配置值
     */
    public Boolean getBoolean(String key, Boolean defaultValue) {
        Object value = getConfiguration(key);
        if (value instanceof Boolean) {
            return (Boolean) value;
        }
        return defaultValue;
    }
    
    /**
     * 检查配置项是否存在
     * 
     * @param key 配置键
     * @return 是否存在
     */
    public boolean hasConfiguration(String key) {
        configLock.readLock().lock();
        try {
            return configurations.containsKey(key);
        } finally {
            configLock.readLock().unlock();
        }
    }
    
    /**
     * 移除配置项
     * 
     * @param key 配置键
     * @return 被移除的配置值
     */
    public Object removeConfiguration(String key) {
        configLock.writeLock().lock();
        try {
            // 检查是否为只读配置
            ConfigurationMetadata configMetadata = metadata.get(key);
            if (configMetadata != null && configMetadata.isReadOnly()) {
                throw new IllegalStateException("Configuration key '" + key + "' is read-only");
            }
            
            Object removedValue = configurations.remove(key);
            metadata.remove(key);
            
            if (removedValue != null) {
                incrementVersion();
                notifyConfigurationChanged(key, removedValue, null);
                log.debug("Configuration removed: {} (was: {})", key, removedValue);
            }
            
            return removedValue;
        } finally {
            configLock.writeLock().unlock();
        }
    }
    
    /**
     * 获取所有配置项
     * 
     * @return 配置项映射的副本
     */
    public Map<String, Object> getAllConfigurations() {
        configLock.readLock().lock();
        try {
            return new HashMap<>(configurations);
        } finally {
            configLock.readLock().unlock();
        }
    }
    
    /**
     * 获取配置元数据
     * 
     * @param key 配置键
     * @return 配置元数据
     */
    public ConfigurationMetadata getMetadata(String key) {
        return metadata.get(key);
    }
    
    /**
     * 批量更新配置
     * 
     * @param newConfigurations 新配置映射
     */
    public void updateConfigurations(Map<String, Object> newConfigurations) {
        if (newConfigurations == null || newConfigurations.isEmpty()) {
            return;
        }
        
        configLock.writeLock().lock();
        try {
            for (Map.Entry<String, Object> entry : newConfigurations.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                
                // 检查只读限制
                ConfigurationMetadata existingMetadata = metadata.get(key);
                if (existingMetadata != null && existingMetadata.isReadOnly()) {
                    log.warn("Skipping read-only configuration: {}", key);
                    continue;
                }
                
                Object oldValue = configurations.put(key, value);
                
                // 更新元数据（如果不存在）
                if (!metadata.containsKey(key)) {
                    metadata.put(key, new ConfigurationMetadata(null, false, System.currentTimeMillis()));
                }
                
                // 通知监听器
                notifyConfigurationChanged(key, oldValue, value);
            }
            
            incrementVersion();
            log.info("Batch updated {} configurations", newConfigurations.size());
            
        } finally {
            configLock.writeLock().unlock();
        }
    }
    
    /**
     * 注册配置变更监听器
     * 
     * @param listener 监听器
     */
    public void addConfigurationChangeListener(ConfigurationChangeListener listener) {
        if (listener != null) {
            listeners.add(listener);
            log.debug("Added configuration change listener: {}", listener.getClass().getSimpleName());
        }
    }
    
    /**
     * 移除配置变更监听器
     * 
     * @param listener 监听器
     */
    public void removeConfigurationChangeListener(ConfigurationChangeListener listener) {
        if (listener != null) {
            listeners.remove(listener);
            log.debug("Removed configuration change listener: {}", listener.getClass().getSimpleName());
        }
    }
    
    /**
     * 通知配置变更
     * 
     * @param key 配置键
     * @param oldValue 旧值
     * @param newValue 新值
     */
    private void notifyConfigurationChanged(String key, Object oldValue, Object newValue) {
        ConfigurationChangeEvent event = new ConfigurationChangeEvent(key, oldValue, newValue, configVersion);
        
        for (ConfigurationChangeListener listener : listeners) {
            try {
                listener.onConfigurationChanged(event);
            } catch (Exception e) {
                log.error("Error notifying configuration change listener", e);
            }
        }
    }
    
    /**
     * 增加配置版本号
     */
    private void incrementVersion() {
        configVersion++;
    }
    
    /**
     * 获取当前配置版本
     * 
     * @return 配置版本号
     */
    public long getConfigVersion() {
        return configVersion;
    }
    
    /**
     * 获取配置统计信息
     * 
     * @return 统计信息
     */
    public Map<String, Object> getStatistics() {
        configLock.readLock().lock();
        try {
            Map<String, Object> stats = new HashMap<>();
            stats.put("totalConfigurations", configurations.size());
            stats.put("configVersion", configVersion);
            stats.put("listeners", listeners.size());
            
            // 按类型统计配置数量
            Map<String, Integer> typeStats = new HashMap<>();
            for (Object value : configurations.values()) {
                String type = value != null ? value.getClass().getSimpleName() : "null";
                typeStats.put(type, typeStats.getOrDefault(type, 0) + 1);
            }
            stats.put("configurationsByType", typeStats);
            
            // 只读配置数量
            long readOnlyCount = metadata.values().stream()
                    .mapToLong(m -> m.isReadOnly() ? 1 : 0)
                    .sum();
            stats.put("readOnlyConfigurations", readOnlyCount);
            
            return stats;
        } finally {
            configLock.readLock().unlock();
        }
    }
    
    /**
     * 重置为默认配置
     */
    public void resetToDefaults() {
        configLock.writeLock().lock();
        try {
            configurations.clear();
            metadata.clear();
            initializeDefaultConfigurations();
            log.info("Configuration reset to defaults");
        } finally {
            configLock.writeLock().unlock();
        }
    }
    
    /**
     * 配置元数据
     */
    public static class ConfigurationMetadata {
        private final String description;
        private final boolean readOnly;
        private final long lastModified;
        
        public ConfigurationMetadata(String description, boolean readOnly, long lastModified) {
            this.description = description;
            this.readOnly = readOnly;
            this.lastModified = lastModified;
        }
        
        public String getDescription() {
            return description;
        }
        
        public boolean isReadOnly() {
            return readOnly;
        }
        
        public long getLastModified() {
            return lastModified;
        }
    }
    
    /**
     * 配置变更事件
     */
    public static class ConfigurationChangeEvent {
        private final String key;
        private final Object oldValue;
        private final Object newValue;
        private final long version;
        private final long timestamp;
        
        public ConfigurationChangeEvent(String key, Object oldValue, Object newValue, long version) {
            this.key = key;
            this.oldValue = oldValue;
            this.newValue = newValue;
            this.version = version;
            this.timestamp = System.currentTimeMillis();
        }
        
        public String getKey() {
            return key;
        }
        
        public Object getOldValue() {
            return oldValue;
        }
        
        public Object getNewValue() {
            return newValue;
        }
        
        public long getVersion() {
            return version;
        }
        
        public long getTimestamp() {
            return timestamp;
        }
    }
    
    /**
     * 配置变更监听器接口
     */
    public interface ConfigurationChangeListener {
        void onConfigurationChanged(ConfigurationChangeEvent event);
    }
}